package main

import (
	"fmt"
	"image/color"
	"io/ioutil"
	"log"
	"math/rand"
	"time"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"github.com/hajimehoshi/ebiten/v2/inpututil"
	"github.com/hajimehoshi/ebiten/v2/text"
	"golang.org/x/image/font"
	"golang.org/x/image/font/basicfont"
	"golang.org/x/image/font/opentype"
)

// 加载中文字体
func loadChineseFont() font.Face {
	// 尝试加载系统中的中文字体
	fontPaths := []string{
		// Windows 中文字体路径
		"C:/Windows/Fonts/simhei.ttf",
		"C:/Windows/Fonts/msyh.ttf",
		// Linux 中文字体路径
		"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
		// macOS 中文字体路径
		"/System/Library/Fonts/PingFang.ttc",
		// 也可以使用项目中的字体文件
		"./assets/fonts/simhei.ttf",
	}

	var fontData []byte
	var err error

	// 尝试从不同路径加载字体
	for _, path := range fontPaths {
		fontData, err = ioutil.ReadFile(path)
		if err == nil {
			break
		}
	}

	// 如果无法加载任何字体，使用基本字体并记录警告
	if err != nil {
		log.Println("警告: 无法加载中文字体，将使用基本字体。中文可能显示为乱码。")
		return basicfont.Face7x13
	}

	// 解析字体
	tt, err := opentype.Parse(fontData)
	if err != nil {
		log.Println("警告: 无法解析字体，将使用基本字体。", err)
		return basicfont.Face7x13
	}

	// 创建字体face
	const dpi = 72
	face, err := opentype.NewFace(tt, &opentype.FaceOptions{
		Size:    16,
		DPI:     dpi,
		Hinting: font.HintingFull,
	})

	if err != nil {
		log.Println("警告: 无法创建字体face，将使用基本字体。", err)
		return basicfont.Face7x13
	}

	return face
}

const (
	screenWidth   = 640
	screenHeight  = 480
	holeCount     = 9   // 洞的数量 (3x3网格)
	holeSize      = 60  // 洞的大小
	moleSize      = 50  // 地鼠的大小
	gridSpacing   = 120 // 洞之间的间距
	minShowTime   = 130 // 地鼠最短显示时间 (帧)
	maxShowTime   = 190 // 地鼠最长显示时间 (帧)
	minHideTime   = 120 // 地鼠最短隐藏时间 (帧)
	maxHideTime   = 160 // 地鼠最长隐藏时间 (帧)
	moleTypeCount = 4   // 地鼠类型数量
	hitEffectTime = 10  // 打击效果持续时间(帧)
)

// 地鼠类型对应的颜色和分数
var moleColors = []color.RGBA{
	{227, 130, 64, 255}, // 普通地鼠 - 棕色
	{255, 215, 0, 255},  // 金色地鼠
	{70, 130, 180, 255}, // 蓝色地鼠
	{255, 0, 0, 255},    // 红色地鼠
}

var moleScores = []int{
	1,  // 普通地鼠 1分
	3,  // 金色地鼠 3分
	5,  // 蓝色地鼠 5分
	10, // 红色地鼠 10分
}

// Mole 表示一个地鼠
type Mole struct {
	x, y       int  // 洞的位置
	visible    bool // 是否可见
	timer      int  // 计时器
	targetTime int  // 目标时间
	moleType   int  // 地鼠类型 (0-3)
	hitEffect  int  // 打击效果计时器
}

// Game 实现了 ebiten.Game 接口
type Game struct {
	moles       [holeCount]Mole
	score       int
	gameOver    bool
	gameTime    int
	maxGameTime int
	font        font.Face
	resetButton struct {
		x, y, w, h int
		hover      bool
	}
	hammerImage *ebiten.Image
	hammerDown  bool // 锤子是否处于下砸状态
	hammerTimer int  // 锤子动画计时器
}

// 初始化游戏
func NewGame() *Game {
	rand.Seed(time.Now().UnixNano())

	g := &Game{
		score:       0,
		gameOver:    false,
		gameTime:    0,
		maxGameTime: 60 * 30, // 30秒游戏时间 (60帧/秒)
		font:        loadChineseFont(),
	}

	// 初始化重置按钮
	g.resetButton.x = screenWidth/2 - 50
	g.resetButton.y = screenHeight - 50
	g.resetButton.w = 100
	g.resetButton.h = 30

	// 初始化地鼠
	for i := 0; i < holeCount; i++ {
		row := i / 3
		col := i % 3
		g.moles[i] = Mole{
			x:          col*gridSpacing + (screenWidth-gridSpacing*3)/2 + gridSpacing/2,
			y:          row*gridSpacing + 100,
			visible:    false,
			timer:      0,
			targetTime: rand.Intn(maxHideTime-minHideTime) + minHideTime,
			moleType:   rand.Intn(moleTypeCount),
			hitEffect:  0,
		}
	}
	// 创建锤子图像
	g.hammerImage = createHammerImage()

	// 隐藏默认光标
	ebiten.SetCursorMode(ebiten.CursorModeHidden)

	return g
}

// 创建锤子图像
func createHammerImage() *ebiten.Image {
	img := ebiten.NewImage(32, 32)

	// 绘制锤子手柄
	ebitenutil.DrawRect(img, 14, 20, 4, 20, color.RGBA{139, 69, 19, 255})

	// 绘制锤子头部
	ebitenutil.DrawRect(img, 8, 0, 16, 10, color.RGBA{255, 255, 255, 255})

	return img
}

// Update 更新游戏状态
func (g *Game) Update() error {
	// 检查游戏是否结束
	if g.gameOver {
		// 检查重置按钮
		x, y := ebiten.CursorPosition()
		g.resetButton.hover = x >= g.resetButton.x && x <= g.resetButton.x+g.resetButton.w &&
			y >= g.resetButton.y && y <= g.resetButton.y+g.resetButton.h

		if g.resetButton.hover && inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
			// 重置游戏
			*g = *NewGame()
		}
		return nil
	}

	// 更新游戏时间
	g.gameTime++
	if g.gameTime >= g.maxGameTime {
		g.gameOver = true
		return nil
	}

	// 检查鼠标点击
	if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
		x, y := ebiten.CursorPosition()
		for i, mole := range g.moles {
			if mole.visible {
				// 检查是否点击了地鼠
				dx := x - mole.x
				dy := y - mole.y
				if dx*dx+dy*dy <= (moleSize/2)*(moleSize/2) {
					// 根据地鼠类型增加分数
					g.score += moleScores[mole.moleType]

					// 设置打击效果
					g.moles[i].hitEffect = hitEffectTime

					// 隐藏地鼠并重置计时器
					g.moles[i].visible = false
					g.moles[i].timer = 0
					g.moles[i].targetTime = rand.Intn(maxHideTime-minHideTime) + minHideTime

					// 重新随机地鼠类型
					g.moles[i].moleType = rand.Intn(moleTypeCount)
				}
			}
		}
	}

	// 更新所有地鼠
	for i := range g.moles {
		mole := &g.moles[i]
		mole.timer++

		// 更新打击效果
		if mole.hitEffect > 0 {
			mole.hitEffect--
		}

		// 检查是否需要改变状态
		if mole.timer >= mole.targetTime {
			mole.visible = !mole.visible
			mole.timer = 0

			if mole.visible {
				// 设置显示时间
				mole.targetTime = rand.Intn(maxShowTime-minShowTime) + minShowTime
				// 随机分配地鼠类型
				mole.moleType = rand.Intn(moleTypeCount)
			} else {
				// 设置隐藏时间
				mole.targetTime = rand.Intn(maxHideTime-minHideTime) + minHideTime
			}
		}
	}

	return nil
}

// Draw 绘制游戏画面
func (g *Game) Draw(screen *ebiten.Image) {
	// 绘制背景
	screen.Fill(color.RGBA{34, 139, 34, 255}) // 绿色背景

	// 绘制所有的洞和地鼠
	for _, mole := range g.moles {
		// 绘制洞
		ebitenutil.DrawCircle(screen, float64(mole.x), float64(mole.y), float64(holeSize/2), color.RGBA{101, 67, 33, 255})

		// 如果地鼠可见，绘制地鼠
		if mole.visible {
			// 地鼠身体 - 根据类型使用不同颜色
			moleColor := moleColors[mole.moleType]
			ebitenutil.DrawCircle(screen, float64(mole.x), float64(mole.y), float64(moleSize/2), moleColor)

			// 地鼠眼睛
			eyeSize := 5.0
			ebitenutil.DrawCircle(screen, float64(mole.x-10), float64(mole.y-10), eyeSize, color.White)
			ebitenutil.DrawCircle(screen, float64(mole.x+10), float64(mole.y-10), eyeSize, color.White)

			// 地鼠鼻子
			ebitenutil.DrawCircle(screen, float64(mole.x), float64(mole.y), eyeSize, color.RGBA{174, 55, 55, 255})
		}

		// 绘制打击效果
		if mole.hitEffect > 0 {
			// 绘制星星或爆炸效果
			starSize := float64(mole.hitEffect) * 2.0
			ebitenutil.DrawCircle(screen, float64(mole.x), float64(mole.y), starSize, color.RGBA{255, 255, 255, 128})

			// 绘制"砰"的文字效果
			text.Draw(screen, "砰!", g.font, mole.x+10, mole.y-10, color.RGBA{255, 255, 0, 255})

		}

	}

	// 显示分数和剩余时间
	remainingTime := (g.maxGameTime - g.gameTime) / 60
	scoreText := fmt.Sprintf("得分: %d   剩余时间: %d秒", g.score, remainingTime)
	text.Draw(screen, scoreText, g.font, 10, 20, color.White)

	// 如果游戏结束，显示游戏结束信息和重置按钮
	if g.gameOver {
		gameOverText := "游戏结束!"
		text.Draw(screen, gameOverText, g.font, screenWidth/2-30, screenHeight/2, color.White)

		// 绘制重置按钮
		buttonColor := color.RGBA{100, 100, 200, 255}
		if g.resetButton.hover {
			buttonColor = color.RGBA{120, 120, 220, 255}
		}
		ebitenutil.DrawRect(screen, float64(g.resetButton.x), float64(g.resetButton.y),
			float64(g.resetButton.w), float64(g.resetButton.h), buttonColor)
		text.Draw(screen, "重新开始", g.font, g.resetButton.x+20, g.resetButton.y+20, color.White)
	}

	// 绘制锤子光标
	x, y := ebiten.CursorPosition()
	op := &ebiten.DrawImageOptions{}

	// 如果鼠标按下，旋转锤子表示敲击动作
	if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
		g.hammerDown = true
		g.hammerTimer = 5 // 设置锤子动画持续时间
	}

	if g.hammerDown {
		// 锤子下砸动画
		op.GeoM.Translate(16, 16) // 将原点移到图像中心
		op.GeoM.Rotate(-1)        // 旋转锤子
		op.GeoM.Translate(0, 16)  // 将原点移回
		g.hammerTimer--

		if g.hammerTimer <= 0 {
			g.hammerDown = false
		}
	}

	// 移动锤子到鼠标位置
	op.GeoM.Translate(float64(x-16), float64(y-16))
	screen.DrawImage(g.hammerImage, op)
}

// Layout 返回游戏的逻辑屏幕大小
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
	return screenWidth, screenHeight
}

func main() {
	// 设置窗口属性
	ebiten.SetWindowSize(screenWidth, screenHeight)
	ebiten.SetWindowTitle("打地鼠游戏")

	// 创建游戏实例并启动游戏循环
	game := NewGame()
	if err := ebiten.RunGame(game); err != nil {
		log.Fatal(err)
	}
}
